#include "AssetManager.h"
#include "container/ResultAttribute.h"
#include "container/Result.h"
#include "../AssetReader.h"
#include "../AssetWriter.h"
namespace XpsAssets
{

	AssetManager::AssetManager(void)
	{
		setDocument("");

	#ifdef _DEBUG
/*		connect(this, SIGNAL(sNewAttribute(int)), this, SLOT(debugPrint(int)));
		connect(this, SIGNAL(sNewQuestion(int)), this, SLOT(debugPrint(int)));
		connect(this, SIGNAL(sNewResult(int)), this, SLOT(debugPrint(int)));*/
	#endif
	}

	AssetManager::~AssetManager(void)
	{
	}

	/// saves current project to file
	void AssetManager::save(QString filename,QList<TreeNode*> tree)
	{
		AssetWriter aw;
		aw.attributes.copyFrom(attributes);
		aw.questions.copyFrom(questions);
		aw.responses.copyFrom(responses);
		aw.results.copyFrom(results);
		aw.tree = tree;
		aw.write(filename);

		setDocument(filename);
		emit sAssetsSaved();
	}

	void AssetManager::cleanUp()
	{
		questions.deleteContent();
		responses.deleteContent();
		attributes.deleteContent();
		results.deleteContent();

		qDeleteAll(treeitems);
		linkqueue.clear();
	}

	/// loads project from file
	void AssetManager::load(QString filename)
	{
		AssetReader ar;
		ar.read(filename);
		emit sAssetsLoaded();

		setDocument(filename);
		questions.copyFrom(ar.questions);
		attributes.copyFrom(ar.attributes);
		results.copyFrom(ar.results);
		responses.copyFrom(ar.responses);
		treeitems = ar.items;
		linkqueue = ar.linkQueue;

		for (int i = 0; i < attributes.count(); i++)
		{
			emit sNewAttribute(attributes.at(i)->id());
		}
		for (int i = 0; i < results.count(); i++)
		{
			emit sNewResult(results.at(i)->id());
		}
		for (int i = 0; i < questions.count(); i++)
		{
			Question* q = questions.at(i);
				
			emit sNewQuestion(q->id());

			for (int j = 0; j < q->responses()->count(); j++)
			{
				Response* r = responses.get(q->responses()->at(j));
				
				if (r == NULL)
					qDebug() << "AssetManager: could not resolve response " << q->responses()->at(j);
				else
					emit sNewResponse(q->id(), r->id());
				
				for (int k = 0; k < r->attributes()->count(); k++)
				{
					emit sNewResponseAttribute(r->id(), r->attributes()->keys().at(k));
				}
			}
		}
		for (int i = 0; i < treeitems.count(); i++)
		{
			TreeNode* node = treeitems.value(treeitems.keys().at(i));
			
			emit sNewTreeNode(node->_id);
		}
		for (int i = 0; i < linkqueue.count(); i+=3)
		{
			emit sNewLink(linkqueue.at(0+i), linkqueue.at(1+i), linkqueue.at(2+i));
		}
	}

	//***************
	// Asset Creator
	//***************

	/// creates a new empty attribute and links it to all existing results
	int AssetManager::createAttribute()
	{
		Attribute* a = attributes.create();

		// append new attribute to all existing results
		for (int i = 0; i < results.count(); i++)
		{
			ResultAttribute* ra = new ResultAttribute();
			results.at(i)->attributes()->insert(a->id(), ra);
		}

		emit sNewAttribute(a->id());
		
		qDebug() << "AssetManager: new attribute";
		return a->id();
	}

	/// creates a new empty question
	int AssetManager::createQuestion()
	{
		Question* q = questions.create();

		emit sNewQuestion(q->id());

		qDebug() << "AssetManager: new question";
		return q->id();
	}

	/// creates a new empty result
	int AssetManager::createResult()
	{
		Result* r = results.create();

		// append all existing attributes to new result
		for (int i = 0; i < attributes.count(); i++)
		{
			ResultAttribute* ra = new ResultAttribute();
			r->attributes()->insert(attributes.at(i)->id(), ra);
		}	

		emit sNewResult(r->id());

		qDebug() << "AssetManager: new result";
		return r->id();
	}
	
	/// creates a new empty response
	int AssetManager::createResponse(int qid)
	{
		Question* q;
		q = questions.get(qid);
		
		if (q == NULL)
		{
			qDebug() << "AssetManager (error): tried to create response for invalid question id";
			return -1;
		}
		Response* r = responses.create();
		q->responses()->append(r->id());

		emit sNewResponse(qid, r->id());

		qDebug() << "AssetManager: new response";
		return r->id();
	}

	/// creates a new empty response
	int AssetManager::createResponseAttribute(int rid, int aid)
	{
		Response* r;

		r = responses.get(rid);

		if (r == NULL)
			return -1;

		r->attributes()->insert(aid, new ResponseAttribute());

		emit sNewResponseAttribute(rid, aid);

		qDebug() << "AssetManager: new response attribute";
		return aid;
	}

	//***************
	// Asset Remover
	//***************

	/// deletes an attribute and all existing links
	void AssetManager::deleteAttribute(int id)
	{
		// remove attribute from all existing results
		for (int i = 0; i < results.count(); i++)
		{
			ResultAttribute* ra = results.at(i)->attributes()->take(id);
			delete ra;
		}

		// remove attribute from all responses
		for (int i = 0; i < questions.count(); i++)
		{
			Question* q = questions.at(i);
			
			for (int j = 0; j < q->responses()->count(); j++)
			{
				Response* r = responses.get(q->responses()->at(j)); 
				
				ResponseAttribute* ra = r->attributes()->take(id);
				delete ra;
			}
		}

		// remove attribute from attributes manager
		attributes.remove(id);
		
		qDebug() << "AssetManager: remove attribute";
		emit sAttributeRemoved(id);
	}

	/// deletes a response attribute 
	void AssetManager::deleteResponseAttribute(int rid, int aid)
	{
		Response* r = responses.get(rid);
		r->attributes()->remove(aid);
		
		qDebug() << "AssetManager: remove response attribute";
		emit sResponseAttributeRemoved(rid,aid);
	}


	/// deletes a result
	void AssetManager::deleteResult(int id)
	{
		results.remove(id);
		qDebug() << "AssetManager: remove result";
		emit sResultRemoved(id);
	}

	/// deletes a response
	void AssetManager::deleteResponse(int qid, int rid)
	{
		Question* q = questions.get(qid);
		q->responses()->removeOne(rid);
		responses.remove(rid);
		
		qDebug() << "AssetManager: remove response";
		emit sResponseRemoved(qid,rid);
	}

	/// deletes a question
	void AssetManager::deleteQuestion(int id)
	{
		questions.remove(id);
		
		qDebug() << "AssetManager: remove question";
		emit sQuestionRemoved(id);
	}

	//****************
	// Asset Accessor
	//****************
	
	TreeNode* AssetManager::getNode(int id)
	{
		return treeitems.value(id);
	}

	Question* AssetManager::getQuestion(int id)
	{
		return questions.get(id);
	}

	Question* AssetManager::getQuestionAt(int pos)
	{
		return questions.at(pos);
	}

	//int AssetManager::getQuestionPos(int id)
	//{
	//	return questions.pos(id);
	//}

	Attribute* AssetManager::getAttribute(int id)
	{
		return attributes.get(id);
	}

	Attribute* AssetManager::getAttributeAt(int pos)
	{
		return attributes.at(pos);
	}

	//int AssetManager::getAttributePos(int id)
	//{
	//	return attributes.pos(id);
	//}

	Response* AssetManager::getResponse(int rid)
	{
		return responses.get(rid);
	}

	Result* AssetManager::getResult(int id)
	{
		return results.get(id);
	}

	int AssetManager::questionCount() 
	{
		return questions.count();
	}
	
	int AssetManager::resultCount()
	{
		return results.count();
	}
	
	int AssetManager::responseCount(int pos)
	{
		return questions.at(pos)->responses()->count();
	}
	
	int AssetManager::attributeCount()
	{
		return attributes.count();
	}
}